package com.wtwd.campus.controller;

import com.alibaba.fastjson.JSONObject;
import com.wtwd.campus.common.Constants;
import com.wtwd.campus.common.RespCode;
import com.wtwd.campus.common.RespEntity;
import com.wtwd.campus.service.LocationService;
import com.wtwd.campus.service.RedisService;
import com.wtwd.campus.utils.CommandSendUtils;
import com.wtwd.campus.utils.DateUtils;
import com.wtwd.campus.utils.GPSUtils;
import com.wtwd.campus.utils.HttpclientUtil;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import java.math.BigDecimal;
import java.util.*;

/**
 * @author zdl
 * @Description
 * @create 2021-06-22 16:58
 */
@RestController
@RequestMapping("location")
public class LocationController {
    private static final Logger log = LoggerFactory.getLogger(LocationController.class);
    static final String lbsUrl = "http://apilocate.amap.com/position";
    static final String LBS_API_KEY = "f4e9efa64ee346968886accf08565d43";

    @Autowired
    private LocationService locationService;
    @Autowired
    private RedisService redisService;
    @Autowired
    private CommandSendUtils commandSendUtils;

    @GetMapping("/info")
    public RespEntity getLocationInfo(@RequestParam String imei, String lbs, String wifi, String key) {
        if (StringUtils.isNotBlank(lbs)) {
            lbs = lbs.replaceAll("!", ",");
        }
        //4c48da250b11,-59|4c48da251a11,-77
        //处理wifi mac地址没有:
        if (StringUtils.isNotBlank(wifi) && wifi.indexOf(":") != 3) {
            String[] split = wifi.split(",");
            for (int i = 0; i < split.length; i++) {
                StringBuffer sb = new StringBuffer(split[i]);
                int index = sb.indexOf("|");
                index = index > 0 ? index + 1 : i == 0 ? 0 : index;
                if (index < 0) {
                    continue;
                }
                sb.insert(10 + index, ":");
                sb.insert(8 + index, ":");
                sb.insert(6 + index, ":");
                sb.insert(4 + index, ":");
                sb.insert(2 + index, ":");
                split[i] = sb.toString();
            }
            wifi = StringUtils.join(split, ",");
        }
        RespEntity result = getLocationByLbsOrWifi(LocationController.LBS_API_KEY, null, imei, lbs, wifi, null, null, null);
        //TODO 高德坐标系转GPS84
        if (0 == result.getCode()) {
            Map<String, Object> data = (HashMap) result.getData();
            double[] doubles = GPSUtils.gcj02_To_Gps84(new Double((String) data.get("lat")), new Double((String) data.get("lng")));
            data.put("lat", new BigDecimal(doubles[0]).setScale(6, BigDecimal.ROUND_DOWN));
            data.put("lng", new BigDecimal(doubles[1]).setScale(6, BigDecimal.ROUND_DOWN));
        }
        return result;
    }

    /**
     * 高德基站,wifi定位服务
     *
     * @param apikey     apikey | 必填
     * @param accesstype 移动接入网络方式 |必填|移动接入网络:0 ,wifi 接入网络:1 默认根据基站和wifi数量
     * @param imei       设备IMEI |必填
     * @param lbs        基站数据|accesstype=0必填|非CDMA mcc,mnc,lac,cellid,signa | 460,01,40977,2205409,-65|460,01,40%20977,2205409,-65 默认第一个为已接入基站
     * @param wifis      wifi数据|accesstype=1必填| mac,signal,ssid | 4c:48:da:25:0b:11,-59,alibaba-inc|4c:48:da:25:1a:11,-77,mywifi 默认第一个为已接入wifi 必须大于2个
     * @param network    无线网络类型|accesstype=0必填|可选值 GSM/GPRS/EDGE/HSUPA/HSDPA/WCDMA/.... 默认 GSM
     * @param isCDMA     是否CDMA|accesstype=0必填|1是,0否
     * @param others     其他参数|非必填|key=value | imsi=1234&serverip=127.0.0.1
     *                   <p>
     *                   为了尽可能地保证您定位结果的精确性，除了必须填写的参数外，其 他可以获得的参数 也请一并传入,
     *                   例如：wifi 接入网络的情况下，也可以传入其对应的基站信息；而在移动接入网络的情况
     *                   下，也可传入 wifi 列表中 mac 信息（macs）
     * @return 返回null 请求参数错误, 返回json字符串{code:0,msg:"成功",data:{lat:"",lng:"",accuracy:"",address:""}}
     * code:
     * 0-成功;100-参数无效;400-未找到数据
     */
    RespEntity getLocationByLbsOrWifi(String apikey, Integer accesstype, String imei, String lbs, String wifis, String network, String isCDMA, String others) {
        int bsNum = 0, wifiNum = 0;
        if (StringUtils.isAnyBlank(apikey, imei)) {
            return new RespEntity(100, "参数无效");
        }
        if (StringUtils.isNotBlank(lbs)) {
            lbs = lbs.replaceAll("!", ",");
            bsNum = lbs.length() - lbs.replaceAll("\\|", "").length() + 1;
        }
        if (StringUtils.isNotBlank(wifis)) {
            wifiNum = wifis.length() - wifis.replaceAll("\\|", "").length() + 1;
        }
        if (bsNum == 0 && wifiNum == 0) {
            //wifi和lbs必须选填一项
            return new RespEntity(100, "参数无效");
        }
        if (accesstype == null) {
            if (wifiNum >= 2) {//wifi个数大于2,wifi接入网络
                accesstype = 1;
            } else {
                accesstype = 0;
            }
        } else {
            if (accesstype > 1) {
                return new RespEntity(100, "参数无效");
            }
        }
        isCDMA = StringUtils.isBlank(isCDMA) ? "0" : isCDMA;
        network = StringUtils.isBlank(network) ? "GSM" : network;
        String bts = null;//接入基站:  非CDMA mcc,mnc,lac,cellid,signa
        String nearbts = null; //建议填,附近基站,不含接入基站

        String mmac = null;//建议填,已连接wifi : mac,signal,ssid。
        String macs = null; //周围wifi|accesstype=1 必填
        //基站数据
        if (bsNum == 1) {
            bts = lbs;
        } else if (bsNum > 1) {
            int index = lbs.indexOf("|");
            bts = lbs.substring(0, index);
            nearbts = lbs.substring(index + 1);
        }
        //wifi 数据
        macs = wifis;
        if (wifiNum == 1) {
            mmac = wifis;
        } else if (wifiNum > 1) {
            int index = wifis.indexOf("|");
            mmac = wifis.substring(0, index);
        }
        StringBuffer lbsUrl = new StringBuffer(LocationController.lbsUrl);
        lbsUrl.append("?key=").append(apikey).append("&accesstype=").append(accesstype)
                .append("&imei=").append(imei);
        if (StringUtils.isNotBlank(isCDMA)) {
            lbsUrl.append("&cdma=").append(isCDMA);
        }
        if (StringUtils.isNotBlank(network)) {
            lbsUrl.append("&network=").append(network);
        }
        if (StringUtils.isNotBlank(bts)) {
            lbsUrl.append("&bts=").append(bts);
        }
        if (StringUtils.isNotBlank(nearbts)) {
            lbsUrl.append("&nearbts=").append(nearbts);
        }
        if (StringUtils.isNotBlank(mmac)) {
            lbsUrl.append("&mmac=").append(mmac);
        }
        if (StringUtils.isNotBlank(macs)) {
            lbsUrl.append("&macs="
            ).append(macs);
        }
        String rep = HttpclientUtil.getForObject(lbsUrl.toString());
        JSONObject result = JSONObject.parseObject(rep);
        if ("0".equals(result.getString("status"))) {
            log.error("[{}]lbs location fail:{}", imei, result.getString("info"));
            return new RespEntity(400, "没有找到数据");
        }
        JSONObject resultJson = result.getJSONObject("result");
        if ("0".equals(resultJson.getString("type"))) {
            log.error("[{}]lbs location fail:{}", imei, resultJson.getString("info"));
            return new RespEntity(400, "没有找到数据");
        }
        String location = resultJson.getString("location");
        HashMap<String, String> data = new HashMap<>();
        String[] lnglat = location.split(",");
        data.put("addr", resultJson.getString("desc"));
        data.put("accuracy", resultJson.getString("radius"));
        data.put("lng", lnglat[0]);
        data.put("lat", lnglat[1]);
        //api 返回 4-基站 ,3-wifi
        data.put("type", resultJson.getInteger("type") == 4 ? "4" : "2");
        return new RespEntity(0, "操作成功", data);
    }

    /**
     * 获取学生定位信息（班级和精确查找单个学生）
     *
     * @param classId
     * @return
     */
    @GetMapping("/getClassesLocation/{classId}/{imei}")
    public RespEntity getClassesLocation(@PathVariable("classId") Integer classId, @PathVariable("imei") String imei,
                                         HttpServletRequest request) {
        log.info("getClassesLocation: classId = {},imei = {}", classId, imei);
        //获取用户组织编码
        String orgCode = getUserOrgCode(request);
        if (!"0".equals(imei)) {
            classId = null;
        } else {
            imei = null;
        }
        List<Map<String, Object>> locationList = locationService.getClassesLocationList(classId, imei, orgCode);
        if (locationList == null || locationList.size() == 0) {
            return new RespEntity(RespCode.NO_DATA);
        }
        return new RespEntity(RespCode.SUCCESS, locationList);
    }


    /**
     * 获取设备定位轨迹
     *
     * @param key
     * @param time
     * @param request
     * @return
     */
    @GetMapping("/getDeviceTrack/{key}/{time}")
    public RespEntity getDeviceTrack(@PathVariable("key") String key, @PathVariable("time") Long time,
                                     HttpServletRequest request) {
        log.info("getDeviceTrack: key = {},time = {}", key, time);
        String orgCode = getUserOrgCode(request);
        List<Map<String, Object>> deviceTrack = locationService.getDeviceTrack(key, time, orgCode);
   /*     //对轨迹数据进行处理筛选
        List<Map<String, Object>> list = dealLocation(deviceTrack);*/
        return new RespEntity(deviceTrack == null || deviceTrack.size() == 0 ? RespCode.NO_TRACK_OR_UNBINDING_STUDENT : RespCode.SUCCESS, deviceTrack);
    }

    /**
     * 获取设备点距离
     *
     * @param imei
     * @param time
     * @return
     */
    @GetMapping("/getDistance/{imei}/{time}")
    public void getDevicePointDistance(@PathVariable("imei") String imei, @PathVariable("time") Long time) {
        List<Map<String, Object>> deviceTrack = locationService.getDeviceTrack(imei, time, "A01");
        if(deviceTrack != null && deviceTrack.size() > 0){
            String longitude = (String) deviceTrack.get(0).get("longitude");
            String latitude = (String) deviceTrack.get(0).get("latitude");
            for (int i = 1; i < deviceTrack.size(); i++) {
                Map<String,Object> map = deviceTrack.get(i);
                String lng = (String)map.get("longitude");
                String lat = (String)map.get("latitude");
                double[] doubles = GPSUtils.gps84_To_Gcj02(Double.parseDouble(latitude), Double.parseDouble(longitude));
                double[] doubles1 = GPSUtils.gps84_To_Gcj02(Double.parseDouble(lat), Double.parseDouble(lng));
                double distance = GPSUtils.getDistance(doubles[1], doubles[0], doubles1[1], doubles1[0]);
                map.put("distance",distance);
                map.put("location_time", DateUtils.format(new Date((long)map.get("location_time")),DateUtils.dateFormat4));
                longitude = lng;
                latitude = lat;
            }
        }
        System.out.println(deviceTrack);
        System.out.println(dealLocation(deviceTrack));
    }


    /**
     * 获取用户组织编码
     *
     * @param request
     * @return
     */
    public String getUserOrgCode(HttpServletRequest request) {
        //获取用户的组织编号
        String token = request.getHeader(Constants.HEADER_TOKEN_KEY);
        Map<String, Object> msg = redisService.getUserInfoByToken(token);
        String userMsg = (String) msg.get("user");
        JSONObject jsonObject = JSONObject.parseObject(userMsg);
        String userOrgCode = (String) jsonObject.get("orgCode");
        return userOrgCode;
    }

    /**
     * 筛选轨迹数据，未超过十米就筛掉
     *
     * @param list
     * @return
     */
    public List<Map<String, Object>> dealLocation(List<Map<String, Object>> list) {
        if (list == null || list.size() <= 2) {
            return list;
        }
        List<Map<String, Object>> result = new ArrayList<>();
        Map<String, Object> curr = list.get(0);
        result.add(curr);
        for (int i = 1; i < list.size() - 1; i++) {
            String longitude = (String) curr.get("longitude");
            String latitude = (String) curr.get("latitude");
            double[] doubles = GPSUtils.gps84_To_Gcj02(Double.parseDouble(latitude), Double.parseDouble(longitude));
            String longitude2 = (String) list.get(i).get("longitude");
            String latitude2 = (String) list.get(i).get("latitude");
            double[] doubles2 = GPSUtils.gps84_To_Gcj02(Double.parseDouble(latitude2), Double.parseDouble(longitude2));
            double distance = GPSUtils.getDistance(doubles[1], doubles[0], doubles2[1], doubles2[0]);
            if (distance > 10) {
                result.add(list.get(i));
                curr = list.get(i);
            }
        }
        result.add(list.get(list.size() - 1));
        return result;
    }
}
